package com.example.exception;

import com.example.pojo.ResponseMessage;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理器
 * 作用：统一捕获和处理项目中所有Controller层抛出的异常
 * 避免异常直接暴露给前端，同时规范异常响应格式
 */
@RestControllerAdvice // 组合注解，等效于 @ControllerAdvice + @ResponseBody
                      // 表示该类是全局异常处理类，且所有方法返回值会自动转为JSON
                      // Spring 会自动扫描带有@RestControllerAdvice注解的类，前提是要满足以下条件：
                      // 组件扫描包配置：Spring 容器默认只会扫描启动类所在包及其子包下的组件。
                      // 如果@RestControllerAdvice标注的类不在这个扫描范围内，需要通过@ComponentScan注解显式指定扫描包路径。
                      // 例如，在 Spring Boot 应用的主启动类上，
                      // 可以通过@ComponentScan(basePackages = {"com.example.controller",
                      // "com.example.exception"})
                      // 来指定扫描路径，确保包含@RestControllerAdvice类的包被扫描到。
                      // 一旦被扫描到，Spring会将带有@RestControllerAdvice注解的类实例化，
                      // 并在合适的时机（如控制器方法抛出异常时）调用其定义的方法来处理相应的业务逻辑。

// 问题?:什么是控制器方法抛出异常时?
// 在基于 Spring MVC 或 Spring Boot 的 Web 应用开发中，
// 控制器方法是控制器类（使用@Controller或@RestController注解的类）里定义的、
// 用于处理客户端请求并返回响应结果的方法 

public class GlobalExceptionHandlerAdvice {
    // 什么异常的统一处理
    // 日志记录器，用于记录异常信息到日志文件
    Logger log = LoggerFactory.getLogger(GlobalExceptionHandlerAdvice.class);

    /**
     * 处理所有未被捕获的异常（Exception类型及其子类）
     * 
     * @param e       捕获到的异常对象
     * @param request 触发异常的HTTP请求对象，可用于获取请求URL等信息
     * @return 统一格式的错误响应对象（ResponseMessage）
     */
    @ExceptionHandler({ Exception.class }) // 注解指定该方法处理的异常类型，这里处理所有Exception及其子类
    public ResponseMessage handlerException(Exception e, HttpServletRequest request) {
        // 记录日志
        log.error("统一异常", e);
        return new ResponseMessage(500, "error", null);
    }
}

// =======================

// 关于 Exception 的说明
// Exception 是 Java 中所有异常类的父类（除了 RuntimeException 的特殊情况，但其本质也是 Exception 的子类），位于
// java.lang 包下。

// 它的核心特点：

// 继承关系：Exception 继承自 Throwable，下面又分为两类：
// 受检异常（Checked Exception）：必须显式捕获或声明抛出（如 IOException）
// 非受检异常（Unchecked Exception）：即 RuntimeException 及其子类，可无需显式处理（如
// NullPointerException）
// 作用：表示程序运行过程中发生的可预期的错误（与 Error 不同，Error 表示不可恢复的严重错误，如内存溢出）。
// 在当前代码中的意义：
// @ExceptionHandler({Exception.class}) 表示该方法会捕获所有类型的异常（因为所有异常都是 Exception 的子类）。
// 这种写法可以作为全局异常处理的兜底方案，确保任何未被专门处理的异常都能被捕获并返回统一格式的响应。

// =============================